home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / misc / aterminfo.lha / lib_tparm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  7.4 KB  |  370 lines

  1.  
  2. /* This work is copyrighted. See COPYRIGHT.OLD & COPYRIGHT.NEW for   *
  3. *  details. If they are missing then this copy is in violation of    *
  4. *  the copyright conditions.                                        */
  5.  
  6. /*
  7.  *    tparm.c
  8.  *
  9.  */
  10.  
  11. #include <string.h>
  12. #include <stdarg.h>
  13. #include "term.h"
  14.  
  15. /*
  16.  *    char *
  17.  *    tparm(string, parms)
  18.  *
  19.  *    Substitute the given parameters into the given string by the following
  20.  *    rules (taken from terminfo(5)):
  21.  *
  22.  *         Cursor addressing and other strings  requiring  parame-
  23.  *    ters in the terminal are described by a parameterized string
  24.  *    capability, with like escapes %x in  it.   For  example,  to
  25.  *    address  the  cursor, the cup capability is given, using two
  26.  *    parameters: the row and column to  address  to.   (Rows  and
  27.  *    columns  are  numbered  from  zero and refer to the physical
  28.  *    screen visible to the user, not to any  unseen  memory.)  If
  29.  *    the terminal has memory relative cursor addressing, that can
  30.  *    be indicated by
  31.  *
  32.  *         The parameter mechanism uses  a  stack  and  special  %
  33.  *    codes  to manipulate it.  Typically a sequence will push one
  34.  *    of the parameters onto the stack and then print it  in  some
  35.  *    format.  Often more complex operations are necessary.
  36.  *
  37.  *         The % encodings have the following meanings:
  38.  *
  39.  *         %%        outputs `%'
  40.  *         %d        print pop() like %d in printf()
  41.  *         %2d       print pop() like %2d in printf()
  42.  *         %02d      print pop() like %02d in printf()
  43.  *         %3d       print pop() like %3d in printf()
  44.  *         %03d      print pop() like %03d in printf()
  45.  *         %c        print pop() like %c in printf()
  46.  *         %s        print pop() like %s in printf()
  47.  *
  48.  *         %p[1-9]   push ith parm
  49.  *         %P[a-z]   set variable [a-z] to pop()
  50.  *         %g[a-z]   get variable [a-z] and push it
  51.  *         %'c'      push char constant c
  52.  *         %{nn}     push integer constant nn
  53.  *
  54.  *         %+ %- %* %/ %m
  55.  *                   arithmetic (%m is mod): push(pop() op pop())
  56.  *         %& %| %^  bit operations: push(pop() op pop())
  57.  *         %= %> %<  logical operations: push(pop() op pop())
  58.  *         %! %~     unary operations push(op pop())
  59.  *         %i        add 1 to first two parms (for ANSI terminals)
  60.  *
  61.  *         %? expr %t thenpart %e elsepart %;
  62.  *                   if-then-else, %e elsepart is optional.
  63.  *                   else-if's are possible ala Algol 68:
  64.  *                   %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
  65.  *
  66.  *    For those of the above operators which are binary and not commutative,
  67.  *    the stack works in the usual way, with
  68.  *            %gx %gy %m
  69.  *    resulting in x mod y, not the reverse.
  70.  */
  71.  
  72. #define STACKSIZE    20
  73.  
  74. typedef union {
  75.     unsigned int    num;
  76.     char            *str;
  77. } stack_frame;
  78.  
  79. stack_frame        stack[STACKSIZE];
  80. static    int        stack_ptr;
  81. static    char    buffer[256];
  82. static    int        param[9];
  83. static    char    *bufptr;
  84. static    int        variable[26];
  85.  
  86. __inline void npush(int x)
  87. {
  88.     if (stack_ptr < STACKSIZE) {
  89.         stack[stack_ptr].num = x;
  90.         stack_ptr++;
  91.     }
  92. }
  93.  
  94. __inline int npop()
  95. {
  96.     return   (stack_ptr > 0  ?  stack[--stack_ptr].num  :  0);
  97. }
  98.  
  99. __inline char *spop()
  100. {
  101.     return   (stack_ptr > 0  ?  stack[--stack_ptr].str  :  0);
  102. }
  103.  
  104. char *
  105. tparm(char *string, ...)
  106. {
  107. va_list    ap;
  108. char    len;
  109. int        number;
  110. int        level;
  111. int        x, y;
  112. int        i;
  113.  
  114.     va_start(ap, string);
  115.     for (i = 0; i < 9; i++) {
  116.         param[i] = va_arg(ap, int);
  117.     }
  118.  
  119. #ifdef TRACE
  120.     if (_tracing)
  121.         _tracef("tparm(%s,%d,%d,%d,%d,%d,%d,%d,%d,%d) called",
  122.             string, param[0], param[1], param[2], param[3],
  123.             param[4], param[5], param[6], param[7], param[8]);
  124. #endif
  125.  
  126.     stack_ptr = 0;
  127.     bufptr = buffer;
  128.  
  129.     while (*string) {
  130.         if (*string != '%')
  131.             *(bufptr++) = *string;
  132.         else {
  133.             string++;
  134.             switch (*string) {
  135.             default:
  136.                 break;
  137.             case '%':
  138.                 *(bufptr++) = '%';
  139.                 break;
  140.  
  141.             case 'd':
  142.                 sprintf(bufptr, "%d", npop());
  143.                 bufptr += strlen(bufptr);
  144.                 break;
  145.  
  146.             case '0':
  147.                 string++;
  148.                 len = *string;
  149.                 if ((len == '2'  ||  len == '3')  &&  *++string == 'd') {
  150.                     if (len == '2')
  151.                         sprintf(bufptr, "%02d", npop());
  152.                         else
  153.                         sprintf(bufptr, "%03d", npop());
  154.  
  155.                     bufptr += strlen(bufptr);
  156.                 }
  157.                 break;
  158.  
  159.             case '2':
  160.                 string++;
  161.                 if (*string == 'd') {
  162.                     sprintf(bufptr, "%2d", npop());
  163.                     bufptr += strlen(bufptr);
  164.                 }
  165.                 break;
  166.  
  167.             case '3':
  168.                 string++;
  169.                 if (*string == 'd') {
  170.                     sprintf(bufptr, "%3d", npop());
  171.                     bufptr += strlen(bufptr);
  172.                 }
  173.                 break;
  174.  
  175.             case 'c':
  176.                 *(bufptr++) = (char) npop();
  177.                 break;
  178.  
  179.             case 's':
  180.                 strcpy(bufptr, spop());
  181.                 bufptr += strlen(bufptr);
  182.                 break;
  183.  
  184.             case 'p':
  185.                 string++;
  186.                 if (*string >= '1'  &&  *string <= '9')
  187.                     npush(param[*string - '1']);
  188.                 break;
  189.  
  190.             case 'P':
  191.                 string++;
  192.                 if (*string >= 'a'  &&  *string <= 'z')
  193.                     variable[*string - 'a'] = npop();
  194.                 break;
  195.  
  196.             case 'g':
  197.                 string++;
  198.                 if (*string >= 'a'  &&  *string <= 'z')
  199.                     npush(variable[*string - 'a']);
  200.                 break;
  201.  
  202.             case '\'':
  203.                 string++;
  204.                 npush(*string);
  205.                 string++;
  206.                 break;
  207.  
  208.             case '{':
  209.                 number = 0;
  210.                 string++;
  211.                 while (*string >= '0'  &&  *string <= '9') {
  212.                     number = number * 10 + *string - '0';
  213.                     string++;
  214.                 }
  215.                 npush(number);
  216.                 break;
  217.  
  218.             case '+':
  219.                 npush(npop() + npop());
  220.                 break;
  221.  
  222.             case '-':
  223.                 y = npop();
  224.                 x = npop();
  225.                 npush(x - y);
  226.                 break;
  227.  
  228.             case '*':
  229.                 npush(npop() * npop());
  230.                 break;
  231.  
  232.             case '/':
  233.                 y = npop();
  234.                 x = npop();
  235.                 npush(x / y);
  236.                 break;
  237.  
  238.             case 'm':
  239.                 y = npop();
  240.                 x = npop();
  241.                 npush(x % y);
  242.                 break;
  243.  
  244.             case '&':
  245.                 npush(npop() & npop());
  246.                 break;
  247.  
  248.             case '|':
  249.                 npush(npop() | npop());
  250.                 break;
  251.  
  252.             case '^':
  253.                 npush(npop() ^ npop());
  254.                 break;
  255.  
  256.             case '=':
  257.                 y = npop();
  258.                 x = npop();
  259.                 npush(x == y);
  260.                 break;
  261.  
  262.             case '<':
  263.                 y = npop();
  264.                 x = npop();
  265.                 npush(x < y);
  266.                 break;
  267.  
  268.             case '>':
  269.                 y = npop();
  270.                 x = npop();
  271.                 npush(x > y);
  272.                 break;
  273.  
  274.             case '!':
  275.                 npush(! npop());
  276.                 break;
  277.  
  278.             case '~':
  279.                 npush(~ npop());
  280.                 break;
  281.  
  282.             case 'i':
  283.                 param[0]++;
  284.                 param[1]++;
  285.                 break;
  286.  
  287.             case '?':
  288.                 break;
  289.  
  290.             case 't':
  291.                 x = npop();
  292.                 if (x) {
  293.                     /* do nothing; keep executing */
  294.                 } else {
  295.                     /* scan forward for %e or %; at level zero */
  296.                     string++;
  297.                     level = 0;
  298.                     while (*string) {
  299.                         if (*string == '%') {
  300.                             string++;
  301.                             if (*string == '?')
  302.                                 level++;
  303.                             else if (*string == ';') {
  304.                                 if (level > 0)
  305.                                     level--;
  306.                                 else
  307.                                 break;
  308.                             }
  309.                             else if (*string == 'e'  && level == 0)
  310.                                 break;
  311.                         }
  312.  
  313.                         if (*string)
  314.                         string++;
  315.                     }
  316.                 }
  317.                 break;
  318.  
  319.             case 'e':
  320.                 /* scan forward for a %; at level zero */
  321.                 string++;
  322.                 level = 0;
  323.                 while (*string) {
  324.                     if (*string == '%') {
  325.                         string++;
  326.                         if (*string == '?')
  327.                             level++;
  328.                         else if (*string == ';') {
  329.                             if (level > 0)
  330.                                 level--;
  331.                             else
  332.                                 break;
  333.                         }
  334.                     }
  335.  
  336.                     if (*string)
  337.                         string++;
  338.                 }
  339.                 break;
  340.  
  341.             case ';':
  342.                 break;
  343.  
  344.             } /* endswitch (*string) */
  345.         } /* endelse (*string == '%') */
  346.  
  347.         if (*string == '\0')
  348.             break;
  349.  
  350.         string++;
  351.     } /* endwhile (*string) */
  352.  
  353.     *bufptr = '\0';
  354.     return(buffer);
  355. }
  356.  
  357. /*
  358.  *    char *
  359.  *    tgoto(string, x, y)
  360.  *
  361.  *    Retained solely for upward compatibility.  Note the intentional
  362.  *    reversing of the last two arguments.
  363.  *
  364.  */
  365.  
  366. char *tgoto(char *string, int x, int y)
  367. {
  368.     return(tparm(string, y, x));
  369. }
  370.